package co.yixiang.yshop.module.member.service.user;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.NumberUtil;
import co.yixiang.yshop.framework.common.enums.ShopCommonEnum;
import co.yixiang.yshop.framework.common.pojo.PageResult;
import co.yixiang.yshop.module.member.controller.admin.user.vo.*;
import co.yixiang.yshop.module.member.controller.admin.userbill.vo.UserBillPageReqVO;
import co.yixiang.yshop.module.member.controller.admin.userbill.vo.UserBillRespVO;
import co.yixiang.yshop.module.member.controller.admin.usertagref.vo.UserTagRefExportReqVO;
import co.yixiang.yshop.module.member.convert.user.UserConvert;
import co.yixiang.yshop.module.member.convert.userbill.UserBillConvert;
import co.yixiang.yshop.module.member.dal.dataobject.user.MemberUserDO;
import co.yixiang.yshop.module.member.dal.dataobject.userlevelgrowthvalueconfig.UserLevelGrowthValueConfigDO;
import co.yixiang.yshop.module.member.dal.dataobject.usertagref.UserTagRefDO;
import co.yixiang.yshop.module.member.dal.mysql.user.MemberUserMapper;
import co.yixiang.yshop.module.member.enums.BillDetailEnum;
import co.yixiang.yshop.module.member.enums.BillTitleEnum;
import co.yixiang.yshop.module.member.enums.LevelGrowthValueEnum;
import co.yixiang.yshop.module.member.service.signinrecord.SignInRecordService;
import co.yixiang.yshop.module.member.service.userbill.UserBillService;
import co.yixiang.yshop.module.member.service.userlevelconfig.UserLevelConfigService;
import co.yixiang.yshop.module.member.service.userlevelgrowthvalueconfig.UserLevelGrowthValueConfigService;
import co.yixiang.yshop.module.member.service.usertagref.UserTagRefService;
import co.yixiang.yshop.module.order.api.productorder.ProductOrderApi;
import co.yixiang.yshop.module.order.api.productorder.dto.StoreOrderDTO;
import co.yixiang.yshop.module.order.enums.OrderStatusEnum;
import co.yixiang.yshop.module.product.api.coupon.CouponApi;
import co.yixiang.yshop.module.product.api.coupon.UserCouponDTO;
import co.yixiang.yshop.module.product.api.productrelation.AppStoreProductRelationQueryDTO;
import co.yixiang.yshop.module.product.api.productrelation.ProductRelationApi;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static co.yixiang.yshop.framework.common.exception.util.ServiceExceptionUtil.exception;
import static co.yixiang.yshop.module.member.enums.ErrorCodeConstants.USER_NOT_EXISTS;

/**
 * 用户 Service 实现类
 *
 * @author yshop
 */
@Service
@Validated
public class UserServiceImpl implements UserService {

    @Resource
    private MemberUserMapper userMapper;
    @Resource
    private UserBillService userBillService;
    @Resource
    private UserTagRefService userTagRefService;
    @Resource
    private UserLevelGrowthValueConfigService growthValueConfigService;
    @Resource
    private UserLevelConfigService levelConfigService;
    @Resource
    private SignInRecordService signInRecordService;
    @Resource
    private ProductOrderApi productOrderApi;
    @Resource
    private CouponApi couponApi;
    @Resource
    private ProductRelationApi productRelationApi;

    @Override
    public Long createUser(UserCreateReqVO createReqVO) {
        // 插入
        MemberUserDO user = UserConvert.INSTANCE.convert(createReqVO);
        userMapper.insert(user);
        // 返回
        return user.getId();
    }

    @Override
    public void updateUser(UserUpdateReqVO updateReqVO) {
        // 校验存在
        validateUserExists(updateReqVO.getId());
        // 更新
        MemberUserDO updateObj = UserConvert.INSTANCE.convert(updateReqVO);
        userMapper.updateById(updateObj);
        //更新用户标签
        this.doUpdateTag(updateReqVO.getId(), updateReqVO.getTagIdList());
    }

    /**
     * 更新金额与积分
     *
     * @param updateReqVO 更新信息
     */
    @Override
    public void updateMoney(UserUpdateMoneyReqVO updateReqVO) {
        MemberUserDO memberUserDO = userMapper.selectById(updateReqVO.getId());
        double newMoney;
        String mark;
        if (updateReqVO.getMoney() != null) {
            if (ShopCommonEnum.ADD_1.getValue().equals(updateReqVO.getPtype())) {
                mark = "系统增加了" + updateReqVO.getMoney() + "余额";
                newMoney = NumberUtil.add(memberUserDO.getNowMoney(), new BigDecimal(updateReqVO.getMoney())).doubleValue();
                userBillService.income(memberUserDO.getId(), BillTitleEnum.SYS_ADD_BALANCE.getValue(), BillDetailEnum.CATEGORY_1.getValue(),
                        BillDetailEnum.TYPE_6.getValue(), BigDecimal.valueOf(Double.parseDouble(updateReqVO.getMoney())), BigDecimal.valueOf(newMoney), mark, "");
            } else {
                mark = "系统扣除了" + updateReqVO.getMoney() + "余额";
                newMoney = NumberUtil.sub(memberUserDO.getNowMoney(), new BigDecimal(updateReqVO.getMoney())).doubleValue();
                if (newMoney < 0) {
                    newMoney = 0d;
                }
                userBillService.expend(memberUserDO.getId(), "系统减少余额",
                        BillDetailEnum.CATEGORY_1.getValue(),
                        BillDetailEnum.TYPE_7.getValue(),
                        Double.parseDouble(updateReqVO.getMoney()), newMoney, mark);
            }
            memberUserDO.setNowMoney(BigDecimal.valueOf(newMoney));
        }
        double newIntegral;
       if(updateReqVO.getIntegral() != null){
           if (ShopCommonEnum.ADD_1.getValue().equals(updateReqVO.getItype())) {
               mark = "系统增加了" + updateReqVO.getIntegral() + "积分";
               newIntegral = NumberUtil.add(memberUserDO.getIntegral(), new BigDecimal(updateReqVO.getIntegral())).doubleValue();
               userBillService.income(memberUserDO.getId(), BillTitleEnum.SYS_ADD_INTEGRAL.getValue(), BillDetailEnum.CATEGORY_2.getValue(),
                       BillDetailEnum.TYPE_6.getValue(), BigDecimal.valueOf(Double.parseDouble(updateReqVO.getIntegral())), BigDecimal.valueOf(newIntegral), mark, "");
           } else {
               mark = "系统扣除了" + updateReqVO.getIntegral() + "积分";
               newIntegral = NumberUtil.sub(memberUserDO.getIntegral(), new BigDecimal(updateReqVO.getIntegral())).doubleValue();
               if (newIntegral < 0) {
                   newIntegral = 0d;
               }
               userBillService.expend(memberUserDO.getId(), "系统减少积分",
                       BillDetailEnum.CATEGORY_2.getValue(),
                       BillDetailEnum.TYPE_7.getValue(),
                       Double.parseDouble(updateReqVO.getIntegral()), newIntegral, mark);
           }
           memberUserDO.setIntegral(BigDecimal.valueOf(newIntegral));
       }
        userMapper.updateById(memberUserDO);

    }


    @Override
    public void deleteUser(Long id) {
        // 校验存在
        validateUserExists(id);
        // 删除
        userMapper.deleteById(id);
    }

    private void validateUserExists(Long id) {
        if (userMapper.selectById(id) == null) {
            throw exception(USER_NOT_EXISTS);
        }
    }

    @Override
    public MemberUserDO getUser(Long id) {
        return userMapper.selectById(id);
    }

    @Override
    public List<MemberUserDO> getUserList(Collection<Long> ids) {
        return userMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<UserRespVO> getUserPage(UserPageReqVO pageReqVO) {
        List<Long> userIds = userTagRefService.getUserIdByTagName(pageReqVO);
        pageReqVO.setUserIds(userIds);
        PageResult<MemberUserDO> pageResult = userMapper.selectPage(pageReqVO);
        PageResult<UserRespVO> result = UserConvert.INSTANCE.convertPage(pageResult);
        // 填充标签等数据
        fillData(result);
        return result;

    }

    /**
     * 填充标签等数据
     *
     * @param result 用户列表
     */
    private void fillData(PageResult<UserRespVO> result) {
        List<Long> resUserIds = result.getList().stream().map(UserRespVO::getId).distinct().collect(Collectors.toList());
        //查询关联标签
        List<UserTagRefDO> userTagRefList = userTagRefService.getUserTagRefList(UserTagRefExportReqVO.builder().userIds(resUserIds).build());
        Map<Long, List<UserTagRefDO>> tagMap = userTagRefList.stream().collect(Collectors.groupingBy(UserTagRefDO::getUserId));

        result.getList().forEach(item -> item.setTagList(tagMap.getOrDefault(item.getId(), ListUtil.empty())));
    }


    @Override
    public List<MemberUserDO> getUserList(UserExportReqVO exportReqVO) {
        return userMapper.selectList(exportReqVO);
    }

    @Override
    public void updateTag(UserUpdateTagDTO dto) {
        this.doUpdateTag(dto.getId(), dto.getTagIdList());
    }

    private void doUpdateTag(Long userId, List<Long> tagIdList) {
        userTagRefService.deleteByUserId(userId);
        if (CollectionUtil.isNotEmpty(tagIdList)) {
            List<UserTagRefDO> collect = tagIdList.stream().map(item -> {
                UserTagRefDO userTagRefDO = new UserTagRefDO();
                userTagRefDO.setUserId(userId);
                userTagRefDO.setTagId(item);
                return userTagRefDO;
            }).collect(Collectors.toList());
            userTagRefService.insertBatch(collect);
        }
    }

    @Override
    public Integer addGrowthValue(Long userId, String type, BigDecimal consumeAmount) {
        //查询对应成长配置
        UserLevelGrowthValueConfigDO growthValueConfig = growthValueConfigService.getByType(type);
        Integer growthValue = 0;
        if (type.equals(LevelGrowthValueEnum.INVITE.getType())) {
            growthValue = growthValueConfig.getGrowthValue();
        } else if (type.equals(LevelGrowthValueEnum.CONSUME.getType())) {
            growthValue = NumberUtil.mul(growthValueConfig.getGrowthValue(), consumeAmount).setScale(0, RoundingMode.DOWN).intValue();
        }
        if (growthValue > 0) {
            userMapper.addGrowthValue(userId, growthValue);
            //升级
            levelConfigService.upgradeLevel(userId);
        }
        return null;
    }

    @Override
    public void updateById(MemberUserDO newUser) {
        userMapper.updateById(newUser);
    }

    @Override
    public void addIntegral(Long userId, BigDecimal integral) {
        userMapper.addIntegral(userId, integral);
    }

    @Override
    public void updateWriteOffAuthority(Long userId, boolean writeOffAuthority) {
        userMapper.updateWriteOffAuthority(userId, writeOffAuthority);
    }

    @Override
    public UserRespVO getUserDetails(Long id) {
        MemberUserDO user = userMapper.selectById(id);
        UserRespVO vo = UserConvert.INSTANCE.convert4(user);
        vo.setSignNum(signInRecordService.countByUserIdThisWeek(id));

        List<UserCouponDTO> userCouponDTOS = couponApi.searchUserCoupon(id);
        vo.setUserCouponDTOS(userCouponDTOS);

        List<AppStoreProductRelationQueryDTO> foot = productRelationApi.userCollectRootProductList(id, "foot");
        vo.setRelationList(foot);

        UserBillPageReqVO pageReqVO = new UserBillPageReqVO();
        pageReqVO.setUid(id);
        pageReqVO.setCategory(BillDetailEnum.CATEGORY_1.getValue());
        pageReqVO.setPageNo(1);
        pageReqVO.setPageSize(20);
        List<UserBillRespVO> billList = UserBillConvert.INSTANCE.convertPage(userBillService.getUserBillPage(pageReqVO)).getList();
        vo.setBillList(billList);

        pageReqVO.setCategory(BillDetailEnum.CATEGORY_2.getValue());
        List<UserBillRespVO> integralBillList = UserBillConvert.INSTANCE.convertPage(userBillService.getUserBillPage(pageReqVO)).getList();
        vo.setIntegralBillList(integralBillList);

        List<StoreOrderDTO> storeOrderDTOS = productOrderApi.orderList(id, OrderStatusEnum.STATUS_PAY.getValue());
        vo.setOrderList(storeOrderDTOS);

        List<UserTagRefDO> userTagRefDOList = userTagRefService.getUserTagRefList(UserTagRefExportReqVO.builder().userId(id).build());
        vo.setTagList(userTagRefDOList);
        return vo;
    }

    @Override
    public void updateUserV2(UserUpdateV2ReqVO updateReqVO) {

    }

}
